package com.info.provider.redis;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mars.app.exception.ErrorCodeMsg;
import com.mars.app.exception.SystemException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * Created by pengshuo on 2018/1/9 9:43
 * Description:
 * Modified By:
 * Version:
 *
 * @author pengshuo
 */
@Service
public class RedisUtil {

    private Logger logger = LogManager.getLogger(this.getClass());

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 添加对象
     */
    public boolean add(final String key, final Object value) {
        try {
            String result = objectMapper.writeValueAsString(value);
            return redisTemplate.execute(new RedisCallback<Boolean>() {
                @Override
                public Boolean doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    connection.set(
                            redisTemplate.getStringSerializer().serialize(key),
                            redisTemplate.getStringSerializer().serialize(result));
                    return true;
                }
            });
        }catch (Exception e){
            logger.error("redis 添加缓存异常 {}",e);
            throw new SystemException(ErrorCodeMsg.STORE_CACHE_FAIL,e);
        }
    }
    /**
     * 添加对象
     */
    public boolean add(final String key, final Long expires, final Object value) {
        try {
            String result = objectMapper.writeValueAsString(value);
            return redisTemplate.execute(new RedisCallback<Boolean>() {
                @Override
                public Boolean doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    connection.setEx(
                            redisTemplate.getStringSerializer().serialize(key),
                            expires,
                            redisTemplate.getStringSerializer().serialize(result)
                    );
                    return true;
                }
            });
        }catch (Exception e){
            logger.error("redis 添加缓存异常 {}",e);
            throw new SystemException(ErrorCodeMsg.STORE_CACHE_FAIL,e);
        }
    }

    /**
     * 添加Map
     */
    public boolean add(final Map<String,String> map) {
        if(map.isEmpty()){
            throw new SystemException(ErrorCodeMsg.STORE_CACHE_FAIL);
        }
        try {
            return redisTemplate.execute(new RedisCallback<Boolean>() {
                @Override
                public Boolean doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    for (Map.Entry<String, String> entry : map.entrySet()) {
                        byte[] key  = serializer.serialize(entry.getKey());
                        byte[] name = serializer.serialize(entry.getValue());
                        connection.setNX(key, name);
                    }
                    return true;
                }
            }, false, true);
        }catch (Exception e){
            logger.error("redis 添加缓存异常 {}",e);
            throw new SystemException(ErrorCodeMsg.STORE_CACHE_FAIL,e);
        }
    }

    /**
     * 删除对象 ,依赖key
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 修改对象
     */
    public boolean update(final String key,final Object value) {
        if (get(key) == null) {
            throw new SystemException(ErrorCodeMsg.GET_CACHE_FAIL);
        }
        try {
            String result = objectMapper.writeValueAsString(value);
            return redisTemplate.execute(new RedisCallback<Boolean>() {
                @Override
                public Boolean doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    connection.set(serializer.serialize(key), serializer.serialize(result));
                    return true;
                }
            });
        }catch (Exception e){
            logger.error("redis 更新缓存异常 {}",e);
            throw new SystemException(ErrorCodeMsg.STORE_CACHE_FAIL,e);
        }
    }

    /**
     * 根据key获取对象
     */
    public Object get(final String keyId) {
        try {
            return redisTemplate.execute(new RedisCallback<Object>() {
                @Override
                public Object doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    byte[] key = serializer.serialize(keyId);
                    byte[] value = connection.get(key);
                    if (value == null) {
                        return null;
                    }
                    return serializer.deserialize(value);
                }
            });
        }catch (Exception e){
            logger.error("redis 获取缓存异常 {}",e);
            throw new SystemException(ErrorCodeMsg.GET_CACHE_FAIL,e);
        }
    }
}
